package com.google.code.yargon.level;

import static com.google.code.yargon.util.Constants.*;

/**
 * Wrapper to store and set and get coordinates for things
 * @author Mika Myllynen
 *
 */
public class Location {
	
	// map coordinates and level
	private int x;
	private int y;
	private int z;
	
	/**
	 * New location 
	 * 
	 * @param x map x-coordinate
	 * @param y map y-coordinate
	 * @param z map z-coordinate
	 */
	public Location(int x, int y, int z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}
	
	/**
	 * New undefined location
	 * 
	 */
	public Location() {
		this.x = 0;
		this.y = 0;
		this.z = 0;;
	}
	
	/**
	 * Get the location x-coordinate
	 * 
	 * @return
	 */
	public int getX() {
		return x;
	}

	/**
	 * Get the location y-coordinate
	 * 
	 * @return
	 */
	public int getY() {
		return y;
	}

	/**
	 * Get the location z-coordinate
	 * 
	 * @return
	 */
	public int getZ() {
		return z;
	}
	
	/**
	 * Set the location x-coordinate
	 * 
	 * @param x
	 */
	public void setX(int x) {
		this.x = x;
	}
	
	/**
	 * Set the location y-coordinate
	 * 
	 * @param y
	 */
	public void setY(int y) {
		this.y = y;
	}

	/**
	 * Set the location z-coordinate
	 * 
	 * @param z
	 */
	public void setZ(int z) {
		this.z = z;
	}
	
	/**
	 * Move THIS location to north, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveNorth() {
		this.y++;
		return this;
	}
	
	/**
	 * Move THIS location to north-east, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveNorthEast() {
		this.x++;
		this.y++;
		return this;
	}
	
	/**
	 * Move THIS location to east, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveEast() {
		this.x++;
		return this;
	}
	
	/**
	 * Move THIS location to south-east, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveSouthEast() {
		this.x++;
		this.y--;
		return this;
	}
	
	/**
	 * Move THIS location to south, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveSouth() {
		this.y--;
		return this;
	}
	
	/**
	 * Move THIS location to south-west, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveSouthWest() {
		this.x--;
		this.y--;
		return this;
	}

	/**
	 * Move THIS location to west, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveWest() {
		this.x--;
		return this;
	}
	
	/**
	 * Move THIS location to north-west, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveNorthWest() {
		this.x--;
		this.y++;
		return this;
	}
	
	/**
	 * Move THIS location to direction d, returns itself with the new coordinates
	 * 
	 * @return
	 */
	public Location moveTo(Direction d) {
		switch(d.getDirection()) {
		case NORTH: 		return moveNorth();
		case NORTH_EAST: 	return moveNorthEast();
		case EAST: 			return moveEast(); 		
		case SOUTH_EAST: 	return moveSouthEast(); 	
		case SOUTH: 		return moveSouth();		
		case SOUTH_WEST: 	return moveSouthWest();	
		case WEST: 			return moveWest();			
		case NORTH_WEST: 	return moveNorthWest();	
		}
		return null;
	}	



	
	/**
	 * Return a NEW location north from this location
	 * 
	 * @return
	 */
	public Location toNorth() {
		return new Location(this.x, this.y + 1, 0);
	}
	
	/**
	 * Return a NEW location north-east from this location
	 * 
	 * @return
	 */
	public Location toNorthEast() {
		return new Location(this.x + 1, this.y + 1, 0);
	}
	
	/**
	 * Return a NEW location east from this location
	 * 
	 * @return
	 */
	public Location toEast() {
		return new Location(this.x + 1, this.y, 0);
	}
	
	/**
	 * Return a NEW location south-east from this location
	 * 
	 * @return
	 */
	public Location toSouthEast() {
		return new Location(this.x + 1, this.y - 1, 0);
	}
	
	/**
	 * Return a NEW location south from this location
	 * 
	 * @return
	 */
	public Location toSouth() {
		return new Location(this.x, this.y - 1, 0);
	}
	
	/**
	 * Return a NEW location south-west from this location
	 * 
	 * @return
	 */
	public Location toSouthWest() {
		return new Location(this.x - 1, this.y - 1, 0);
	}
	
	/**
	 * Return a NEW location west from this location
	 * 
	 * @return
	 */
	public Location toWest() {
		return new Location(this.x - 1, this.y, 0);
	}
	
	/**
	 * Return a NEW location north-west from this location
	 * 
	 * @return
	 */
	public Location toNorthWest() {
		return new Location(this.x - 1, this.y + 1, 0);
	}
	
	public Location toDirection(Direction d) {
		switch(d.getDirection()) {
		case NORTH: return toNorth();
		case NORTH_EAST: return toNorthEast();
		case EAST: return toEast();
		case SOUTH_EAST: return toSouthEast();
		case SOUTH: return toSouth();
		case SOUTH_WEST: return toSouthWest();
		case WEST: return toWest();
		case NORTH_WEST: return toNorthWest();
		}
		return null;
	}
	
	/**
	 * Return true if this Location equals given Location
	 * 
	 * @param l
	 * @return boolean value
	 */
	public boolean equals(Location l) {
		if(this.getX() == l.getX() && this.getY() == l.getY() && this.getZ() == l.getZ()) {
			return true;
		}
		return false;
	}
	
	/**
	 * Return the coordinates as a string
	 * 
	 */
	public String toString() {
		return "("+x+","+y+","+z+")";
	}
}
